View Javadoc

1   /*
2    * Copyright 2001-2004 The Apache Software Foundation.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.geronimo.ews.jaxrpcmapping;
17  
18  import org.apache.axis.i18n.Messages;
19  import org.apache.axis.utils.ClassUtils;
20  import org.apache.axis.wsdl.gen.Generator;
21  import org.apache.axis.wsdl.gen.NoopFactory;
22  import org.apache.axis.wsdl.symbolTable.BindingEntry;
23  import org.apache.axis.wsdl.symbolTable.CollectionElement;
24  import org.apache.axis.wsdl.symbolTable.MessageEntry;
25  import org.apache.axis.wsdl.symbolTable.PortTypeEntry;
26  import org.apache.axis.wsdl.symbolTable.ServiceEntry;
27  import org.apache.axis.wsdl.symbolTable.SymTabEntry;
28  import org.apache.axis.wsdl.symbolTable.SymbolTable;
29  import org.apache.axis.wsdl.symbolTable.Type;
30  import org.apache.axis.wsdl.symbolTable.TypeEntry;
31  import org.apache.axis.wsdl.toJava.Emitter;
32  import org.apache.axis.wsdl.toJava.Namespaces;
33  import org.apache.axis.wsdl.toJava.Utils;
34  import org.apache.geronimo.ews.ws4j2ee.context.J2EEWebServiceContext;
35  import org.apache.geronimo.ews.ws4j2ee.toWs.GenerationFault;
36  
37  import javax.wsdl.Binding;
38  import javax.wsdl.Definition;
39  import javax.xml.namespace.QName;
40  import java.io.FileInputStream;
41  import java.io.IOException;
42  import java.io.InputStream;
43  import java.util.Collection;
44  import java.util.Enumeration;
45  import java.util.HashMap;
46  import java.util.Iterator;
47  import java.util.Map;
48  import java.util.Properties;
49  import java.util.Vector;
50  
51  /***
52   * @author Ias (iasandcb@tmax.co.kr)
53   */
54  
55  public class J2eeEmitter extends Emitter {
56  
57      private String mappingFilePath;
58      private static final int timeoutms = 45000000;
59      private InputStream mappingFileInputStream;
60      private QName serviceQName;
61      private JaxRpcMapper jaxRpcMapper;
62      private SymbolTable symbolTable;
63      protected J2EEWebServiceContext wscontext;
64  
65      public J2eeEmitter() {
66          J2eeGeneratorFactory factory = new J2eeGeneratorFactory(this);
67          setFactory(factory);
68      } // ctor
69  
70      public J2eeEmitter(J2EEWebServiceContext wscontext, J2eeGeneratorFactory factory) {
71          this.wscontext = wscontext;
72          if (factory == null)
73              factory = new J2eeGeneratorFactory(this);
74          setFactory(factory);
75          factory.setEmitter(this);
76      } // ctor
77  
78      public void setMappingFilePath(String mappingFilePath) {
79          this.mappingFilePath = mappingFilePath;
80      }
81  
82      private void loadMapping() throws GenerationFault {
83          //jaxRpcMapper = new JAXBJaxRpcMapper();
84          jaxRpcMapper = new XMLBeansJaxRpcMapper();
85          if (mappingFilePath == null) {
86              jaxRpcMapper.loadMappingFromInputStream(mappingFileInputStream);
87          } else {
88              jaxRpcMapper.loadMappingFromDir(mappingFilePath);
89          }
90          setNowrap(!jaxRpcMapper.hasWrappedElement());
91          int length = jaxRpcMapper.getPackageMappingCount();
92          Map namespaceMap = getNamespaceMap();
93          for (int i = 0; i < length; i++) {
94              namespaceMap.put(jaxRpcMapper.getPackageMappingURI(i), jaxRpcMapper.getPackageMappingClassName(i));
95          }
96      }
97  
98      /***
99       * Emit appropriate Java files for a WSDL at a given URL.
100      * This method will time out after the number of milliseconds specified
101      * by our timeoutms member.
102      */
103     public void run(String wsdlURL) throws Exception {
104         setup();
105         runTemp(wsdlURL);
106     } // run
107 
108     public void runServerSide(String wsdlURL) throws Exception {
109         setup();
110         if (getFactory() == null) {
111             setFactory(new NoopFactory());
112         }
113         symbolTable = new SymbolTable(getFactory().getBaseTypeMapping(),
114                 imports,
115                 verbose,
116                 nowrap);
117         symbolTable.setQuiet(quiet);
118         symbolTable.setWrapArrays(wrapArrays);
119         symbolTable.populate(wsdlURL, username, password);
120         generate(symbolTable);
121     }
122 
123     public SymbolTable getSymbolTable() {
124         return symbolTable;
125     }
126 
127     private void setup() throws GenerationFault {
128         try {
129             if (baseTypeMapping == null) {
130                 setTypeMappingVersion(typeMappingVersion);
131             }
132             getFactory().setBaseTypeMapping(baseTypeMapping);
133             namespaces = new Namespaces(getOutputDir());
134             if (getPackageName() != null) {
135                 namespaces.setDefaultPackage(getPackageName());
136             } else {
137                 // First, read the namespace mapping file - configurable, by default
138                 // NStoPkg.properties - if it exists, and load the namespaceMap HashMap
139                 // with its data.
140                 getNStoPkgFromPropsFile(namespaces);
141                 loadMapping();
142                 if (getNamespaceMap() != null) {
143                     namespaces.putAll(getNamespaceMap());
144                 }
145             }
146         } catch (IOException e) {
147             e.printStackTrace();
148             throw GenerationFault.createGenerationFault(e);
149         }
150     } // setup
151 
152     /***
153      * Tries to load the namespace-to-package mapping file.
154      * <ol>
155      * <li>if a file name is explicitly set using <code>setNStoPkg()</code>, tries
156      * to load the mapping from this file. If this fails, the built-in default
157      * mapping is used.
158      * <li>if no file name is set, tries to load the file <code>DEFAULT_NSTOPKG_FILE</code>
159      * as a java resource. If this fails, the built-in dfault mapping is used.
160      * </ol>
161      *
162      * @param namespaces a hashmap which is filled with the namespace-to-package mapping
163      *                   in this method
164      * @see #setNStoPkg(String)
165      * @see #DEFAULT_NSTOPKG_FILE
166      * @see org.apache.axis.utils.ClassUtils#getResourceAsStream(java.lang.Class,String)
167      */
168     private void getNStoPkgFromPropsFile(HashMap namespaces) throws IOException {
169         Properties mappings = new Properties();
170         if (NStoPkgFilename != null) {
171             try {
172                 mappings.load(new FileInputStream(NStoPkgFilename));
173                 if (verbose) {
174                     System.out.println(Messages.getMessage("nsToPkgFileLoaded00", NStoPkgFilename));
175                 }
176             } catch (Throwable t) {
177                 // loading the custom mapping file failed. We do not try
178                 // to load the mapping from a default mapping file.
179                 throw new IOException(Messages.getMessage("nsToPkgFileNotFound00", NStoPkgFilename));
180             }
181         } else {
182             try {
183                 mappings.load(new FileInputStream(DEFAULT_NSTOPKG_FILE));
184                 if (verbose) {
185                     System.out.println(Messages.getMessage("nsToPkgFileLoaded00", DEFAULT_NSTOPKG_FILE));
186                 }
187             } catch (Throwable t) {
188                 try {
189                     mappings.load(ClassUtils.getResourceAsStream(Emitter.class, DEFAULT_NSTOPKG_FILE));
190                     if (verbose) {
191                         System.out.println(Messages.getMessage("nsToPkgDefaultFileLoaded00", DEFAULT_NSTOPKG_FILE));
192                     }
193                 } catch (Throwable t1) {
194                     // loading the default mapping file failed.
195                     // The built-in default mapping is used
196                     // No message is given, since this is generally what happens
197                 }
198             }
199         }
200         Enumeration keys = mappings.propertyNames();
201         while (keys.hasMoreElements()) {
202             String key = (String) keys.nextElement();
203             namespaces.put(key, mappings.getProperty(key));
204         }
205     } // getNStoPkgFromPropsFile
206 
207     /***
208      * Convert the specified QName into a full Java Name.
209      */
210     public String getJavaName(QName qName) {
211         // If this is one of our special 'collection' qnames.
212 
213         // get the element type and append []
214 
215         if (qName.getLocalPart().indexOf("[") > 0) {
216             String localPart = qName.getLocalPart().substring(0, qName.getLocalPart().indexOf("["));
217             QName eQName = new QName(qName.getNamespaceURI(), localPart);
218             return getJavaName(eQName) + "[]";
219         }
220 
221 
222 
223         // Handle the special "java" namespace for types
224 
225         if (qName.getNamespaceURI().equalsIgnoreCase("java")) {
226             return qName.getLocalPart();
227         }
228 
229 
230 
231         // The QName may represent a base java name, so check this first
232 
233         String fullJavaName = getFactory().getBaseTypeMapping().getBaseName(qName);
234         if (fullJavaName != null)
235             return fullJavaName;
236 
237 
238 
239         // Use the namespace uri to get the appropriate package
240 
241         String pkg = getPackage(qName.getNamespaceURI());
242         if (pkg != null) {
243             fullJavaName = pkg + "." + Utils.xmlNameToJavaClass(qName.getLocalPart());
244         } else {
245             fullJavaName = Utils.xmlNameToJavaClass(qName.getLocalPart());
246         }
247         return fullJavaName;
248     } // getJavaName
249 
250     /***
251      * Parse a WSDL at a given URL.
252      * This method will time out after the number of milliseconds specified
253      * by our timeoutms member.
254      */
255     public void runTemp(String wsdlURI) throws Exception {
256         if (getFactory() == null) {
257             setFactory(new NoopFactory());
258         }
259         symbolTable = new SymbolTable(getFactory().getBaseTypeMapping(),
260                 imports,
261                 verbose,
262                 nowrap);
263         symbolTable.setQuiet(quiet);
264         symbolTable.setWrapArrays(wrapArrays);
265 // We run the actual Emitter in a thread that we can kill
266         WSDLRunnable runnable = new WSDLRunnable(symbolTable, wsdlURI);
267         Thread wsdlThread = new Thread(runnable);
268         wsdlThread.start();
269         try {
270             if (timeoutms > 0)
271                 wsdlThread.join(timeoutms);
272             else
273                 wsdlThread.join();
274         } catch (InterruptedException e) {
275         }
276         if (wsdlThread.isAlive()) {
277             wsdlThread.interrupt();
278             throw new IOException(Messages.getMessage("timedOut"));
279         }
280         if (runnable.getFailure() != null) {
281             throw runnable.getFailure();
282         }
283     } // run
284 
285     private class WSDLRunnable implements Runnable {
286         private SymbolTable symbolTable;
287         private String wsdlURI;
288         private Exception failure = null;
289 
290         public WSDLRunnable(SymbolTable symbolTable, String wsdlURI) {
291             this.symbolTable = symbolTable;
292             this.wsdlURI = wsdlURI;
293         } // ctor
294 
295         public void run() {
296             try {
297                 symbolTable.populate(wsdlURI, username, password);
298                 generate(symbolTable);
299             } catch (Exception e) {
300                 failure = e;
301             }
302         } // run
303 
304         public Exception getFailure() {
305             return failure;
306         } // getFailure
307     } // WSDLRunnable
308 
309     protected void sanityCheck(SymbolTable symbolTable) {
310         Iterator it = symbolTable.getHashMap().values().iterator();
311         while (it.hasNext()) {
312             Vector v = (Vector) it.next();
313             for (int i = 0; i < v.size(); ++i) {
314                 SymTabEntry entry = (SymTabEntry) v.elementAt(i);
315                 String namespace = entry.getQName().getNamespaceURI();
316                 String packageName =
317                         org.apache.axis.wsdl.toJava.Utils.makePackageName(namespace);
318                 String localName = entry.getQName().getLocalPart();
319                 if (localName.equals(packageName) &&
320                         packageName.equals(namespaces.getCreate(namespace))) {
321                     packageName += "_pkg";
322                     namespaces.put(namespace, packageName);
323                 }
324             }
325         }
326     }
327 
328     private void generate(SymbolTable symbolTable) throws IOException {
329         sanityCheck(symbolTable);
330         Definition def = symbolTable.getDefinition();
331         getFactory().generatorPass(def, symbolTable);
332         if (isDebug()) {
333             symbolTable.dump(System.out);
334         }
335         if (getOutputDir() == null) {
336             return;
337         }
338 
339         // Generate bindings for types
340         generateTypes(symbolTable);
341         Iterator it = symbolTable.getHashMap().values().iterator();
342         while (it.hasNext()) {
343             Vector v = (Vector) it.next();
344             for (int i = 0; i < v.size(); ++i) {
345                 SymTabEntry entry = (SymTabEntry) v.elementAt(i);
346                 Generator gen = null;
347                 if (entry instanceof MessageEntry) {
348                     gen = getFactory().getGenerator(((MessageEntry) entry).getMessage(), symbolTable);
349                 } else if (entry instanceof PortTypeEntry) {
350                     PortTypeEntry pEntry = (PortTypeEntry) entry;
351                     // If the portType is undefined, then we're parsing a Definition
352                     // that didn't contain a portType, merely a binding that referred
353                     // to a non-existent port type.  Don't bother writing it.
354                     if (pEntry.getPortType().isUndefined()) {
355                         continue;
356                     }
357                     gen = getFactory().getGenerator(pEntry.getPortType(), symbolTable);
358                 } else if (entry instanceof BindingEntry) {
359                     BindingEntry bEntry = (BindingEntry) entry;
360                     Binding binding = bEntry.getBinding();
361 
362                     // If the binding is undefined, then we're parsing a Definition
363                     // that didn't contain a binding, merely a service that referred
364                     // to a non-existent binding.  Don't bother writing it.
365                     if (binding.isUndefined() || !bEntry.isReferenced()) {
366                         continue;
367                     }
368                     gen = getFactory().getGenerator(binding, symbolTable);
369                 } else if (entry instanceof ServiceEntry) {
370                     ServiceEntry sEntry = (ServiceEntry) entry;
371                     serviceQName = sEntry.getService().getQName();
372                     gen = getFactory().getGenerator(sEntry.getService(), symbolTable);
373                 }
374                 if (gen != null) {
375                     gen.generate();
376                 }
377             }
378         }
379 
380         // Output extra stuff (deployment files and faults)
381         // outside of the recursive emit method.
382         Generator gen = getFactory().getGenerator(def, symbolTable);
383         gen.generate();
384     } // generate
385 
386     /***
387      * Generate bindings (classes and class holders) for the complex types.
388      * If generating serverside (skeleton) spit out beanmappings
389      */
390     private void generateTypes(SymbolTable symbolTable) throws IOException {
391         Map elements = symbolTable.getElementIndex();
392         Collection elementCollection = elements.values();
393         for (Iterator i = elementCollection.iterator(); i.hasNext();) {
394             TypeEntry type = (TypeEntry) i.next();
395             type.setOnlyLiteralReference(false);
396 
397             // Write out the type if and only if:
398             //  - we found its definition (getNode())
399             //  - it is referenced
400             //  - it is not a base type
401             //  - it is a Type (not an Element) or a CollectionElement
402             // (Note that types that are arrays are passed to getGenerator
403             //  because they may require a Holder)
404 
405             // A CollectionElement is an array that might need a holder
406 
407             boolean isType = ((type instanceof Type)
408                              || (type instanceof CollectionElement));
409 
410                      if ((type.getNode() != null)
411                     && !type.getNode().getLocalName().equals("attributeGroup")
412                     && !type.getNode().getLocalName().equals("group")
413                              && type.isReferenced() && isType
414                              && (type.getBaseType() == null)) {
415                          Generator gen = getFactory().getGenerator(type, symbolTable);
416 
417                          gen.generate();
418                      }
419         }
420         Map types = symbolTable.getTypeIndex();
421         Collection typeCollection = types.values();
422         for (Iterator i = typeCollection.iterator(); i.hasNext();) {
423             TypeEntry type = (TypeEntry) i.next();
424 
425             // Write out the type if and only if:
426             //  - we found its definition (getNode())
427             //  - it is referenced
428             //  - it is not a base type
429             //  - it is a Type (not an Element) or a CollectionElement
430             // (Note that types that are arrays are passed to getGenerator
431             //  because they may require a Holder)
432 
433             // A CollectionElement is an array that might need a holder
434 
435             boolean isType = (type instanceof Type || type instanceof CollectionElement);
436             if (type.getNode() != null
437                     && !type.getNode().getLocalName().equals("attributeGroup")
438                     && !type.getNode().getLocalName().equals("group") &&
439                     type.isReferenced() &&
440                     isType &&
441                     type.getBaseType() == null) {
442                 Generator gen = getFactory().getGenerator(type, symbolTable);
443                 gen.generate();
444             }
445         }
446     } // generateTypes
447 
448     /***
449      * @param mappingFileInputStream The mappingFileInputStream to set.
450      */
451     public void setMappingFileInputStream(InputStream mappingFileInputStream) {
452         this.mappingFileInputStream = mappingFileInputStream;
453     }
454 
455     /***
456      * @return Returns the serviceQName.
457      */
458     public QName getServiceQName() {
459         return serviceQName;
460     }
461 
462     /***
463      * @return
464      */
465     public boolean isGeneratingInterface() {
466         // TODO Auto-generated method stub
467         return false;
468     }
469 
470     /***
471      * @return
472      */
473     public boolean isGeneratingTypes() {
474         // TODO Auto-generated method stub
475         return false;
476     }
477 
478     /***
479      * @return Returns the jaxRpcMapper.
480      */
481     public JaxRpcMapper getJaxRpcMapper() {
482         return jaxRpcMapper;
483     }
484 
485     /***
486      * @param jaxRpcMapper The jaxRpcMapper to set.
487      */
488     public void setJaxRpcMapper(JaxRpcMapper jaxRpcMapper) {
489         this.jaxRpcMapper = jaxRpcMapper;
490     }
491 
492     /***
493      * @return
494      */
495     public J2EEWebServiceContext getWscontext() {
496         return wscontext;
497     }
498 
499     /***
500      * @param context
501      */
502     public void setWscontext(J2EEWebServiceContext context) {
503         wscontext = context;
504     }
505 
506 } // class MyEmitter